//////////////////////////////////////////////////////////////////////////////////////////////////////
// 项目名   : Container
// 文件名   : TestMultiMap.h
// 作者     : Aiye
// 日期     : 2025/9/4 22:21
// 邮箱     : 2878548868@qq.com
// 摘要     : 介绍multimap
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CONTAINER_TESTMULTIMAP_H
#define CONTAINER_TESTMULTIMAP_H
#include <iostream>
#include <map>
#include <string>
#include <vector>

/**
 * @brief 介绍可重复的集合
 */
class TestMultiSet
{
public:
    /**
     * @brief 构造函数
     */
    static void Constructor()
    {
        std::multimap<int, int> nnMap{}; // 使用默认比较函数std::less
        std::multimap<int, int, std::greater<>> nnMap2{}; // 按照降序进行排序

        std::vector<std::pair<int, std::string>> prVec
        {
            {1, "One"}, {2, "two"}, {3, "three"},
            {1, "first"}, {2, "second"}
        };

        std::multimap nstrMap3(prVec.begin(), prVec.end()); // 可以省略冗余模板参数
        auto nstrMap4{nstrMap3}; // 拷贝构造，深拷贝
        auto nstrMap5{std::move(nstrMap4)}; // 移动构造

        std::multimap<int, std::string> nstrMap6
        {
            {1, "One"}, {2, "two"}, {3, "three"},
            {1, "first"}, {2, "second"}
        }; // 初始化列表构造
    }

    /**
     * @brief 容量
     */
    static void Capacity()
    {
        std::multimap<int, std::string> nstrMap
        {
            {1, "One"}, {2, "two"}, {3, "three"},
            {1, "first"}, {2, "second"}
        }; // 初始化列表构造

        std::cout << "Szie: " << nstrMap.size() << std::endl; // 包含重复元素的数量
        std::cout << "Empty:" << nstrMap.empty() << std::endl; // 判读是否为空

        std::cout << "Max size:" << nstrMap.max_size(); // 获取最大元素数量
    }

    /**
     * @brief 元素访问
     */
    static void Interview()
    {
        std::multimap<int, std::string> nstrMap
        {
            {1, "One"}, {2, "two"}, {3, "three"},
            {1, "first"}, {2, "second"}
        }; // 初始化列表构造

        // multimap不支持[] 运算符、也不支持at，因为一个键可能要对应多个值

        // 访问元素的唯一方式就是通过迭代器
        auto range = nstrMap.equal_range(1);
        for (auto it = range.first ; it != it->second ; ++it)
        {
            std::cout << it->second << std::endl;
        }
    }

    /**
     * @brief 增加
     */
    static void Add()
    {
        std::multimap<int, std::string> nstrMmap;

        // 使用insert()插入元素
        // 插入单个元素，返回指向新元素的迭代器（不返回bool，因为总是成功）
        auto it = nstrMmap.insert({1, "one"});

        // 使用insert()插入多个元素（注意：可以插入重复键）
        nstrMmap.insert({{1, "first"}, {2, "two"}, {1, "second_one"}});

        // 使用emplace()直接构造元素（C++11）
        nstrMmap.emplace(3, "three");

        // 使用emplace_hint()带提示位置的构造（C++11）
        nstrMmap.emplace_hint(nstrMmap.end(), 4, "four");
    }

    static void Delete()
    {
        std::multimap<int, std::string> myMultimap =
        {
            {1, "one"}, {2, "two"}, {1, "first"}, {3, "three"}, {4, "four"}
        };

        // 通过键删除元素，返回删除的元素数量（可能大于1）
        size_t count = myMultimap.erase(1); // 删除所有键为1的元素

        // 通过迭代器删除元素
        auto it = myMultimap.find(2);
        if (it != myMultimap.end())
        {
            myMultimap.erase(it);
        }

        // 删除一个范围内的元素
        auto first = myMultimap.find(3);
        auto last = myMultimap.end();
        myMultimap.erase(first, last); // 删除从键3开始到末尾的所有元素

        // 删除所有元素
        myMultimap.clear();
    }

    static void Modifaction()
    {
        std::multimap<int, std::string> myMultimap = {{1, "one"}, {2, "two"}, {1, "first"}};

        // 错误：不能修改键，因为键是const的
        // auto it = myMultimap.begin();
        // it->first = 10; // 错误

        // 可以修改值（但要注意，值不影响排序）
        auto it = myMultimap.begin();
        it->second = "modified one"; // 允许修改值

        // 更安全的修改方式：先删除再插入（特别是如果要修改键的话）
        // 例如，将键为1的所有元素的值改为"new_value"
        auto range = myMultimap.equal_range(1);
        for (auto it = range.first; it != range.second; )
        {
            // 先保存键和新的值
            int key = it->first;
            std::string new_value = "new_value";
            // 删除当前元素，并返回下一个元素的迭代器
            it = myMultimap.erase(it);
            // 插入新元素
            myMultimap.insert({key, new_value});
        }
    }

    static void Find()
    {
        std::multimap<int, std::string> myMultimap =
        {
            {1, "one"}, {2, "two"}, {1, "first"}, {3, "three"}, {4, "four"}
        };

        // 使用find()查找元素（返回第一个匹配的元素的迭代器）
        auto it = myMultimap.find(1);
        if (it != myMultimap.end())
        {
            std::cout << "Found: " << it->first << " => " << it->second << std::endl;
        }

        // 使用count()检查键出现的次数
        size_t count = myMultimap.count(1);
        std::cout << "Key 1 appears " << count << " times." << std::endl;

        // 使用lower_bound()和upper_bound()进行范围查找
        // 查找所有键大于等于2且小于4的元素
        auto low = myMultimap.lower_bound(2);
        auto up = myMultimap.upper_bound(4);
        for (auto it = low; it != up; ++it)
        {
            std::cout << it->first << " => " << it->second << std::endl;
        }

        // 使用equal_range()获取匹配键的范围（返回一个pair<iterator, iterator>）
        auto range = myMultimap.equal_range(1);
        for (auto it = range.first; it != range.second; ++it)
        {
            std::cout << it->first << " => " << it->second << std::endl;
        }
    }


};
#endif //CONTAINER_TESTMULTIMAP_H
